//
//  SDImageCacheEx.m
//  SKinDiary
//
//  Created by pcyang on 16/6/26.
//  Copyright © 2016年 tencent. All rights reserved.
//

#import "SDImageCacheEx.h"

#import "SDCacheManagement.h"
#import "SDDownloadRequestOperation.h"

#define IMAGECACHE_SIZE_128				134217728//128*1024*1024
#define IMAGECACHE_SIZE_256				268435456//256*1024*1024
#define IMAGECACHE_SIZE_512				536870912//512*1024*1024
#define IMAGECACHE_SIZE_1024			1073741824//1024*1024*1024

#define IMAGECACHE_SIZE_MAX				15728640//20*1024*1024
#define LOCALIMAGECACHE_NUM_MAX         2500

#define TimeIntervalOneDay              86400//24*60*60

@interface SDImageLocalCacheManagement : NSObject <SDCleanCacheProtocol>
@property (nonatomic,retain) NSString   *localCacheDirectory;
@property (nonatomic,assign) UIBackgroundTaskIdentifier backgroundTaskIdentifier;
@property (nonatomic,retain) NSRecursiveLock   *lock;
@end

@implementation SDImageLocalCacheManagement
IMP_SINGLETON;

- (id)init
{
    self = [super init];
    if( self )
    {
        self.lock = [[NSRecursiveLock alloc]init];
        self.localCacheDirectory = [SDFile getDirectoryInCacheWithName:NSStringFromClass([self class])];
        
        [self checkCurLocalCache];
        
        [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(appEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil];
    }
    return self;
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter]removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil];
}

- (void)appEnterBackground
{
    [self checkCurLocalCache];
}

- (NSString*)cachePathWithKey:(NSString*)key
{
    return [NSString stringWithFormat:@"%@/%@",self.localCacheDirectory,[key MD5EncodedString]];
}

- (BOOL)hasLacalCacheWithKey:(NSString*)key
{
    return [SDFile fileExist:[self cachePathWithKey:key]];
}

- (id)getLocalCacheWithKey:(NSString*)key
{
    [self.lock lock];
    NSString* newPath = [self cachePathWithKey:key];
    NSData* image = [NSData dataWithContentsOfFile:newPath];
    //    image = [image decodedImage];
    [SDFile setItemModifed:newPath];
    [self.lock unlock];
    
    return image;
}

- (void)removeLocalCacheWithKey:(NSString*)key
{
    [self.lock lock];
    NSString* path = [self cachePathWithKey:key];
    [SDFile deleteItem:path];
    [self.lock unlock];
}

- (void)removeAllLocalCaches
{
    [self.lock lock];
    [SDFile deleteItem:self.localCacheDirectory];
    [SDFile checkDirectoryPath:self.localCacheDirectory];
    [self.lock unlock];
}

+ (void)cleanCache
{
    [[SDImageLocalCacheManagement sharedInstance]removeAllLocalCaches];
}

- (void)checkCurLocalCache
{
    self.backgroundTaskIdentifier = [[UIApplication sharedApplication]beginBackgroundTaskWithExpirationHandler:^{
        [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskIdentifier];
        self.backgroundTaskIdentifier = UIBackgroundTaskInvalid;
    }];
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self.lock lock];
        
        NSFileManager* defaultManager = [NSFileManager defaultManager];
        
        NSArray* allFiles = [defaultManager contentsOfDirectoryAtPath:self.localCacheDirectory error:nil];
        NSInteger number = [allFiles count];
        if( number > LOCALIMAGECACHE_NUM_MAX )
        {
            NSMutableArray* retainedFiles = [allFiles mutableCopy];
            NSInteger deleteDay = 30;
            do {
                [[self class] removeFilesBefore:[NSDate dateWithTimeIntervalSinceNow:-deleteDay*TimeIntervalOneDay] inLocalCache:retainedFiles];
                deleteDay--;
            } while ([retainedFiles count] > LOCALIMAGECACHE_NUM_MAX*0.8);
        }
        
        [self.lock unlock];
        
        [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskIdentifier];
        self.backgroundTaskIdentifier = UIBackgroundTaskInvalid;
    });
}

+ (void)removeFilesBefore:(NSDate*)date inLocalCache:(NSMutableArray*)allCacheFiles
{
    NSMutableArray* deletedArray = [NSMutableArray arrayWithCapacity:[allCacheFiles count]];
    for (NSString* filePath in allCacheFiles)
    {
        NSDate* fileModifiedTime = [SDFile getItemModifiedTime:filePath];
        if( [fileModifiedTime earlierDate:date] )
        {
            [SDFile deleteItem:filePath];
            [deletedArray addObject:filePath];
        }
    }
    [allCacheFiles removeObjectsInArray:deletedArray];
}



- (BOOL)hasLacalCacheWithURL:(NSString*)url
{
    return [self hasLacalCacheWithKey:url];
}

- (UIImage*)getLocalCacheWithURL:(NSString*)url
{
    [self.lock lock];
    NSString* newPath = [self cachePathWithKey:url];
    UIImage* image = [UIImage imageWithContentsOfFile:newPath];
    //    image = [image decodedImage];
    [SDFile setItemModifed:newPath];
    [self.lock unlock];
    
    return image;
}

- (NSString*)moveImageFrom:(NSString*)srcPath toLocalCacheWithURL:(NSString*)url
{
    [self.lock lock];
    NSString* newPath = [self cachePathWithKey:url];
    [SDFile moveFileFrom:srcPath to:newPath];
    [SDFile setItemModifed:newPath];
    [self.lock unlock];
    return newPath;
}
@end

typedef UIImage* (^TUTImageRequestConfigureImageModifyBlock)(UIImage* data);
typedef void (^TUTImageRequestConfigureImageComletion)(UIImage* data);

@interface SDImageRequestConfigure : NSObject
@property (nonatomic,strong)        NSString*                                       requestIdentifier;
@property (nonatomic,copy)          TUTImageRequestConfigureImageModifyBlock         modifyBlock;
@property (nonatomic,copy)          TUTImageRequestConfigureImageComletion           completion;
@property (nonatomic,strong)        NSString*                                       modifyIdentifier;
@end

@implementation SDImageRequestConfigure
@end

static dispatch_queue_t localCacheImage_operation_queue() {
    static dispatch_queue_t localCacheImage_operation_queue;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        localCacheImage_operation_queue = dispatch_queue_create("com.request.imagecache.localCache", DISPATCH_QUEUE_SERIAL);
    });
    
    return localCacheImage_operation_queue;
}

static dispatch_queue_t processImage_operation_queue() {
    static dispatch_queue_t processImage_operation_queue;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        processImage_operation_queue = dispatch_queue_create("com.request.imagecache.processimage", DISPATCH_QUEUE_CONCURRENT);
    });
    
    return processImage_operation_queue;
}

@interface SDImageCacheEx ()
@property (nonatomic,strong) NSCache*               imageCache;
@property (nonatomic,strong) NSMutableDictionary*   httpInfo; //key:URL value:array of configure info
@property (nonatomic,strong) NSMutableDictionary*   requests; //key:URL value:request
@property (nonatomic,strong) NSRecursiveLock*       lock;

//@property (nonatomic,strong) NSOperationQueue*      imageRequestCallbackQueue;
//@property (nonatomic,strong) NSMutableDictionary*   imageRequestCallbackOperations; //key:URL value:array of the operations
//@property (nonatomic,strong) NSRecursiveLock*       imageRequestCallbackLock;
@end

@implementation SDImageCacheEx (MemoryCache)
- (UIImage *)cachedImageForKey:(NSString *)url {
    return [self.imageCache objectForKey:url];
}

- (void)cacheImageWithInfo:(NSDictionary*)info
{
    [info enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
        [self cacheImage:obj withKey:key];
        
    }];
}

- (void)cacheImage:(UIImage *)image withKey:(NSString *)key
{
    if (image && [self.imageCache objectForKey:key]==nil && [image isKindOfClass:[UIImage class]] && key && [key isKindOfClass:[NSString class]]) {
        CGImageRef CGImage = image.CGImage;
        if( CGImage == nil )return;
        size_t imageDataSize = CGImageGetWidth(CGImage)*CGImageGetHeight(CGImage)*CGImageGetBitsPerPixel(CGImage)/CGImageGetBitsPerComponent(CGImage);
        [self.imageCache setObject:image forKey:key cost:imageDataSize];
    }
}

- (void)clearCacheWithKey:(NSString*)key
{
    [self.imageCache removeObjectForKey:key];
}
@end

@implementation SDImageCacheEx (ProcessImage)
static dispatch_semaphore_t processImage_semaphore() {
    static dispatch_semaphore_t processImage_semaphore;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        processImage_semaphore = dispatch_semaphore_create(5);
    });
    
    return processImage_semaphore;
}

- (void)processImage:(UIImage*)image withURL:(NSString*)url
{
    if( !url )return;
    NSString* urlKey = [url MD5EncodedString];
    if( !urlKey )return;
    
    dispatch_semaphore_wait(processImage_semaphore(), DISPATCH_TIME_FOREVER);
    
    [self.lock lock];
    
    NSArray* configures = [self.httpInfo objectForKey:url];
    [self.httpInfo removeObjectForKey:url];
    
    NSMutableDictionary* imageDic = [NSMutableDictionary dictionaryWithCapacity:[configures count]];
    
    for (SDImageRequestConfigure* configure in configures)
    {
        UIImage* newImage = nil;
        if( image )
        {
            if( configure.modifyBlock)
            {
                newImage = configure.modifyBlock(image);
                
                if( configure.modifyIdentifier )
                {
                    urlKey = [urlKey stringByAppendingString:configure.modifyIdentifier];
                }
                if(newImage)
                    [imageDic setObject:newImage forKey:urlKey];
            }
            else
            {
                newImage = [imageDic objectForKey:urlKey];
                if( newImage == nil )
                {
                    newImage = [image decodedImage];
                    [imageDic setObject:newImage forKey:urlKey];
                }
            }
        }
        
        if( configure.completion )
        {
            [self displayImage:newImage withCompletion:configure.completion];
        }
    }
    
    [self.lock unlock];
    
    [self cacheImageWithInfo:imageDic];
    
    dispatch_semaphore_signal(processImage_semaphore());
    
    
    
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.requests removeObjectForKey:url];
    });
    
}

- (void)displayImage:(UIImage*)image withCompletion:(void (^)(UIImage *image))completion
{
    dispatch_async(dispatch_get_main_queue(), ^{
        completion(image);
    });
}
@end

@implementation SDImageCacheEx (Downloading)
//- (NSOperationQueuePriority)priorityForDownloadingImage:(NSString*)url
//{
//    [self.lock lock];
//    NSArray* configures = [self.httpInfo objectForKey:url];
//    NSArray* priorities = [configures valueForKey:@"priorty"];
//
//    NSOperationQueuePriority priority = NSOperationQueuePriorityVeryLow;
//    for (NSNumber* curPriority in priorities)
//        priority = MAX(priority, [curPriority integerValue]);
//
//    [self.lock unlock];
//
//    return priority;
//}

//- (void)dispatchDownloadingMessage:(long long)downloadSize totalSize:(long long)totalSize withURL:(NSString*)url
//{
//    [self.lock lock];
//
//    NSArray* configures = [self.httpInfo objectForKey:url];
//    NSArray* downloadStatusBlocks = [configures valueForKey:@"statusBlock"];
//
//    for (WYImageRequestConfigureImageDownloadStatusBlock curBlock in downloadStatusBlocks)
//    {
//        if([curBlock isKindOfClass:[NSNull class]] == FALSE)
//        {
//            curBlock(downloadSize,totalSize);
//        }
//    }
//
//    [self.lock unlock];
//}

- (void)clearDownloadingInfoWithURL:(NSString*)url
{
    [self.lock lock];
    [self.httpInfo removeObjectForKey:url];
    [self.lock unlock];
    
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.requests removeObjectForKey:url];
    });
}

- (void)startDownloadImage:(NSString*)url priority:(SDHttpRequestPriority)priority
{
    //    NSOperationQueuePriority realImmediately = [self priorityForDownloadingImage:url];
    SDDownloadRequestOperation* imageRequest = [self.requests objectForKey:url];
    
    if( imageRequest )
    {
        //        imageRequest.queuePriority = realImmediately;
        //        imageRequest = (WYImageRequestOperation*)[[WYHttpClient sharedInstance] resetPriorityForHttpRequestOperation:imageRequest withPriority:realImmediately];
        //        [self.requests setObject:imageRequest forKey:url];
    }
    else
    {
        imageRequest = [[SDDownloadRequestOperation alloc]initWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]];
        imageRequest.queuePriority = NSOperationQueuePriorityLow;
        [self.requests setObject:imageRequest forKey:url];
        
        __weak __typeof(&*imageRequest)weakOperation = imageRequest;
        [imageRequest setCompletionBlock:^{
            __strong __typeof(&*weakOperation)strongOperation = weakOperation;
            
            NSError* error = strongOperation.error;
            
            NSDictionary *headers = [strongOperation.response allHeaderFields];
            //X-ErrNo: -6101
            //X-Info: default-notexist:-6101
            BOOL bSuccess = YES;
            if([headers isKindOfClass:[NSDictionary class]]){
                id errNoObj = [headers objectForKey:@"X-ErrNo"];
                int errCode = 0;
                if(errNoObj != nil){
                    if([errNoObj isKindOfClass:[NSString class]]){
                        errCode=[(NSString*)errNoObj intValue];
                    }else if([errNoObj isKindOfClass:[NSNumber class]]){
                        errCode=[(NSNumber*)errNoObj intValue];
                    }
                }
                if(errCode != 0){
                    bSuccess = NO;
                    //NSLog(@"DownloadImageError:xError:%ld url:%@",(long)errCode,url);
                }
            }
            
            UIImage* image = nil;
            if(bSuccess && !error && strongOperation.cachePath )
            {
                NSString* path = [[SDImageLocalCacheManagement sharedInstance]moveImageFrom:strongOperation.cachePath toLocalCacheWithURL:url];
                if (IsEffectiveString(path))
                {
                    NSData* data = [NSData dataWithContentsOfFile:path];
                    if (data) {
                        image = [UIImage imageWithData:data];
                    }
                    
                }
            }
            
            dispatch_async(processImage_operation_queue(), ^{
                [self processImage:image withURL:url];
            });
        }];
        
        [[SDHttpRequestManagement sharedInstance]addHttpRequest:imageRequest withPriority:priority];
    }
}

- (void)stopDownloadingImage:(NSString*)url identifier:(NSString*)identifier
{
    if( url == nil )return;
    
    [self.lock lock];
    
    NSMutableArray* configures = [self.httpInfo objectForKey:url];
    if( identifier )
    {
        NSIndexSet* stoppedIdentifier = [configures indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
            SDImageRequestConfigure* configure = obj;
            if( [configure.requestIdentifier isEqualToString:identifier] )return TRUE;
            return FALSE;
        }];
        [configures removeObjectsAtIndexes:stoppedIdentifier];
    }
    
    BOOL stop = ([configures count] <= 0 || !identifier);
    if( stop )
    {
        [self.httpInfo removeObjectForKey:url];
        
        [self.lock unlock];
        
        SDDownloadRequestOperation* request = [self.requests objectForKey:url];
        [request cancel];
        [self.requests removeObjectForKey:url];
    }
    else
    {
        [self.lock unlock];
        
        //        NSOperationQueuePriority realImmediately = [self priorityForDownloadingImage:url];
        //        TUTDownloadRequestOperation* imageRequest = [self.requests objectForKey:url];
        //        imageRequest.queuePriority = realImmediately;
    }
}
@end

@implementation SDImageCacheEx
@synthesize imageCache,httpInfo,requests,lock;
//@synthesize imageRequestCallbackQueue,imageRequestCallbackOperations,imageRequestCallbackLock;
IMP_SINGLETON;

- (id)init
{
    self = [super init];
    
    if( self )
    {
        self.imageCache = [[NSCache alloc]init];
        
        unsigned long long physicalMemory = [NSProcessInfo processInfo].physicalMemory;
        if( physicalMemory <= IMAGECACHE_SIZE_128 )
            self.imageCache.totalCostLimit = IMAGECACHE_SIZE_MAX;
        else if( physicalMemory <= IMAGECACHE_SIZE_256 )
            self.imageCache.totalCostLimit = IMAGECACHE_SIZE_MAX*2;
        else if( physicalMemory <= IMAGECACHE_SIZE_512 )
            self.imageCache.totalCostLimit = IMAGECACHE_SIZE_MAX*4;
        else if( physicalMemory <= IMAGECACHE_SIZE_1024 )
            self.imageCache.totalCostLimit = IMAGECACHE_SIZE_MAX*8;
        else
            self.imageCache.totalCostLimit = IMAGECACHE_SIZE_MAX*10;
        
        self.httpInfo = [[NSMutableDictionary alloc]initWithCapacity:20];
        self.requests = [[NSMutableDictionary alloc]initWithCapacity:20];
        
        self.lock = [[NSRecursiveLock alloc] init];
        
        [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(appReceiveMomoryWarning) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
    }
    
    return self;
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter]removeObserver:self name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
}


- (void)appReceiveMomoryWarning
{
    [self.imageCache removeAllObjects];
    NSLog(@"imageCache appReceiveMomoryWarning");
    
}

- (NSString*)pathWithNameInMainBundle:(NSString*)name
{
    //    return [[NSBundle mainBundle]pathForResource:[name stringByDeletingPathExtension] ofType:[name pathExtension]];
    static NSString* s_mainBundlePath = nil;
    
    if(nil==s_mainBundlePath)
    {
        @synchronized(self)
        {
            if(nil==s_mainBundlePath)
                s_mainBundlePath = [NSBundle mainBundle].bundlePath;
        }
    }
    
    return [s_mainBundlePath stringByAppendingPathComponent:name];
    
}

//- (UIImage*)getMemoryImageWithNameInMainBundle:(NSString*)name
//{
//    return [self getMemoryImageWithNameInMainBundle:name modifyIdentifier:nil];
//}
//
//- (UIImage*)getMemoryImageWithNameInMainBundle:(NSString*)name modifyIdentifier:(NSString*)modifyIdentifier;
//{
//    return [self getMemoryImageWithURL:[self pathWithNameInMainBundle:name] modifyIdentifier:modifyIdentifier];
//}
//

- (void)deleteCatchImageWithURL:(NSString*)url
{
    NSString* key = [url MD5EncodedString];
    [self clearCacheWithKey:key];
    [[SDImageLocalCacheManagement sharedInstance] removeLocalCacheWithKey:url];
}

- (UIImage*)getMemoryImageWithURL:(NSString*)url
{
    NSString* key = [url MD5EncodedString];
    return [self cachedImageForKey:key];
}
//
- (UIImage*)getLocalImageWithURL:(NSString*)url
{
    return [[SDImageLocalCacheManagement sharedInstance] getLocalCacheWithURL:url];
}
//- (UIImage*)getMemoryImageWithIdentifier:(NSString*)identifier
//{
//    return [self cachedImageForKey:identifier];
//}


//- (void)getImageWithNameInMainBundle:(NSString*)name
//                    requestConfigure:(WYImageRequestConfigure*)requestConfigure
//{
//    [self getImageWithURL:[self pathWithNameInMainBundle:name] requestConfigure:requestConfigure];
//}

- (void)getImageWithIdentifier:(NSString*)identifier
                 creationBlock:(UIImage* (^)(void))block
                    completion:(void (^)(UIImage *image))completion;
{
    if( identifier == nil )return;
    
    UIImage* image = [self cachedImageForKey:identifier];
    if( image || block == nil )
    {
        if(completion)completion(image);
        return;
    }
    
    dispatch_async(localCacheImage_operation_queue(), ^{
        UIImage* image = block();
        [self cacheImage:image withKey:identifier];
        if(completion)[self displayImage:image withCompletion:completion];
    });
}

- (void)getImageWithNameInMainBundle:(NSString*)name
                          completion:(void (^)(UIImage *image))completion
{
    [self getImageWithURL:[self pathWithNameInMainBundle:name]
               identifier:nil modifyBlock:Nil modifyIdentifier:nil completion:completion];
}

- (void)getImageWithURL:(NSString*)url
             identifier:(NSString*)identifier
             completion:(void (^)(UIImage *image))completion
{
    [self getImageWithURL:url identifier:identifier priority:SDHttpRequestPriority_Low modifyBlock:nil modifyIdentifier:nil completion:completion];
}

- (void)getImageWithURL:(NSString*)url
             identifier:(NSString*)identifier
            modifyBlock:(UIImage* (^)(UIImage* image))block
       modifyIdentifier:(NSString*)modifyIdentifier
             completion:(void (^)(UIImage *image))completion
{
    [self getImageWithURL:url identifier:identifier priority:SDHttpRequestPriority_Low modifyBlock:block modifyIdentifier:modifyIdentifier completion:completion];
}

- (void)getImageWithURL:(NSString*)url
             identifier:(NSString*)identifier
               priority:(SDHttpRequestPriority)priority
            modifyBlock:(UIImage* (^)(UIImage* image))block
       modifyIdentifier:(NSString*)modifyIdentifier
             completion:(void (^)(UIImage *image))completion
{
    SDImageRequestConfigure* configure = [[SDImageRequestConfigure alloc]init];
    configure.requestIdentifier = identifier;
    configure.modifyBlock = block;
    configure.completion = completion;
    configure.modifyIdentifier = modifyIdentifier;
    [self getImageWithURL:url priority:priority requestConfigure:configure];
}

- (void)getLocalImageWithURL:(NSString*)url
                  identifier:(NSString*)identifier
                  completion:(void (^)(UIImage *image))completion
{
    SDImageRequestConfigure* requestConfigure = [[SDImageRequestConfigure alloc]init];
    requestConfigure.requestIdentifier = identifier;
    requestConfigure.modifyBlock = nil;
    requestConfigure.completion = completion;
    requestConfigure.modifyIdentifier = nil;
    
    if(!url)return;
    
    BOOL isFilePath = [[NSURL URLWithString:url]isFileURL];
    BOOL isRequestInfoValid = FALSE;
    if( isFilePath )isRequestInfoValid = [SDFile fileExist:url];
    else isRequestInfoValid = TRUE;
    if( !isRequestInfoValid )return;
    
    NSString* key = [url MD5EncodedString];
    if( requestConfigure.modifyIdentifier )
    {
        key = [key stringByAppendingString:requestConfigure.modifyIdentifier];
    }
    
    UIImage* image = [self cachedImageForKey:key];
    if( image )
    {
        if(requestConfigure.completion)requestConfigure.completion(image);
        return;
    }
    [self.lock lock];
    
    NSMutableArray* configures = [self.httpInfo objectForKey:url];
    if( configures == nil )
    {
        configures = [NSMutableArray arrayWithCapacity:10];
        [self.httpInfo setObject:configures forKey:url];
    }
    [configures addObject:requestConfigure];
    
    [self.lock unlock];
    
    BOOL donotNeedDownload = isFilePath;
    if( !donotNeedDownload )
    {
        donotNeedDownload = [[SDImageLocalCacheManagement sharedInstance]hasLacalCacheWithURL:url];
    }
    
    if( donotNeedDownload )
    {
        dispatch_async(localCacheImage_operation_queue(), ^{
            UIImage* localImage = nil;
            if( isFilePath )
            {
                localImage = [UIImage imageWithContentsOfFile:url];
            }
            else
            {
                localImage = [[SDImageLocalCacheManagement sharedInstance]getLocalCacheWithURL:url];
            }
            if( localImage )
            {
                dispatch_async(processImage_operation_queue(), ^{
                    [self processImage:localImage withURL:url];
                });
            }
            else if( isFilePath )
            {
                dispatch_async(processImage_operation_queue(), ^{
                    [self processImage:nil withURL:url];
                });
            }
        });
        return;
    }
}



- (void)getImageWithURL:(NSString*)url
               priority:(SDHttpRequestPriority)priority
       requestConfigure:(SDImageRequestConfigure*)requestConfigure
{
    if(!url)return;
    
    BOOL isFilePath = [[NSURL URLWithString:url]isFileURL];
    BOOL isRequestInfoValid = FALSE;
    if( isFilePath )isRequestInfoValid = [SDFile fileExist:url];
    else isRequestInfoValid = TRUE;
    if( !isRequestInfoValid )return;
    
    NSString* key = [url MD5EncodedString];
    if( requestConfigure.modifyIdentifier )
    {
        key = [key stringByAppendingString:requestConfigure.modifyIdentifier];
    }
    
    UIImage* image = [self cachedImageForKey:key];
    if( image )
    {
        if(requestConfigure.completion)requestConfigure.completion(image);
        return;
    }
    [self.lock lock];
    
    NSMutableArray* configures = [self.httpInfo objectForKey:url];
    if( configures == nil )
    {
        configures = [NSMutableArray arrayWithCapacity:10];
        [self.httpInfo setObject:configures forKey:url];
    }
    [configures addObject:requestConfigure];
    
    [self.lock unlock];
    
    BOOL donotNeedDownload = isFilePath;
    if( !donotNeedDownload )
    {
        donotNeedDownload = [[SDImageLocalCacheManagement sharedInstance]hasLacalCacheWithURL:url];
    }
    
    if( donotNeedDownload )
    {
        dispatch_async(localCacheImage_operation_queue(), ^{
            UIImage* localImage = nil;
            if( isFilePath )
            {
                localImage = [UIImage imageWithContentsOfFile:url];
            }
            else
            {
                localImage = [[SDImageLocalCacheManagement sharedInstance]getLocalCacheWithURL:url];
            }
            if( localImage )
            {
                dispatch_async(processImage_operation_queue(), ^{
                    [self processImage:localImage withURL:url];
                });
            }
            else if( isFilePath )
            {
                dispatch_async(processImage_operation_queue(), ^{
                    [self processImage:nil withURL:url];
                });
            }
            else
            {
                dispatch_async(dispatch_get_main_queue(), ^{
                    [self startDownloadImage:url priority:priority];
                });
            }
        });
        return;
    }
    
    [self startDownloadImage:url priority:priority];
}

- (UIImage*)getImageWithPath:(NSString*)path
{
    NSString* key = [path MD5EncodedString];
    UIImage* image = [self cachedImageForKey:key];
    if( image == nil )
    {
        image = [UIImage imageWithContentsOfFile:path];
        [self cacheImage:image withKey:key];
    }
    return image;
}

- (UIImage*)getImageWithNameInMainBundle:(NSString*)name
{
    NSString* path = [self pathWithNameInMainBundle:name];
    NSString* key = [path MD5EncodedString];
    UIImage* image = [self cachedImageForKey:key];
    if( image == nil )
    {
        image = [UIImage imageWithContentsOfFile:path];
        [self cacheImage:image withKey:key];
    }
    
    return image;
}

- (void)stopGettingImage:(NSString*)url identifier:(NSString*)identifier
{
    if( url == nil )return;
    
    [self stopDownloadingImage:url identifier:identifier];
}

- (void)clearMemoryImageWithNameInMainBundle:(NSString*)name
{
    [self clearMemoryImageWithNameInMainBundle:name modifyIdentifier:nil];
}

- (void)clearMemoryImageWithNameInMainBundle:(NSString*)name modifyIdentifier:(NSString*)modifyIdentifier
{
    [self clearMemoryImageWithURL:[self pathWithNameInMainBundle:name] modifyIdentifier:modifyIdentifier];
}

- (void)clearMemoryImageWithURL:(NSString*)url modifyIdentifier:(NSString*)modifyIdentifier
{
    NSString* key = [url MD5EncodedString];
    if( modifyIdentifier )
        key = [key stringByAppendingString:modifyIdentifier];
    [self clearMemoryImageWithIdentifier:key];
}

- (void)clearMemoryImageWithIdentifier:(NSString*)identifier
{
    [self clearCacheWithKey:identifier];
}
@end
